package com.zmm.xiaohashu.auth.service.impl;

import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.zmm.framework.common.enums.DeletedEnum;
import com.zmm.framework.common.enums.StatusEnum;
import com.zmm.framework.common.exception.BizException;
import com.zmm.framework.common.response.Response;
import com.zmm.framework.common.utils.JsonUtils;
import com.zmm.xiaohashu.auth.constant.RedisKeyConstants;
import com.zmm.xiaohashu.auth.constant.RoleConstants;
import com.zmm.xiaohashu.auth.domain.dataobject.UserDO;
import com.zmm.xiaohashu.auth.domain.dataobject.UserRoleDO;
import com.zmm.xiaohashu.auth.domain.mapper.UserDOMapper;
import com.zmm.xiaohashu.auth.domain.mapper.UserRoleDOMapper;
import com.zmm.xiaohashu.auth.enums.LoginTypeEnum;
import com.zmm.xiaohashu.auth.enums.ResponseCodeEnum;
import com.zmm.xiaohashu.auth.model.vo.user.UserLoginReqVO;
import com.zmm.xiaohashu.auth.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;

import java.time.LocalDateTime;
import java.util.List;

/**
 * @Author: 福禄寿
 * @Date: 2024/9/10 下午4:32
 * @Des: xiaohashu
 **/
@Service
@Slf4j
public class UserServiceImpl implements UserService {


    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private UserDOMapper userDOMapper;

    @Autowired
    private UserRoleDOMapper userRoleDOMapper;

    @Autowired
    private TransactionTemplate transactionTemplate;

    /**
     * 登录与注册
     *
     * @param userLoginReqVO
     * @return
     */
    @Override
    public Response loginAndRegister(UserLoginReqVO userLoginReqVO) {
        String phone = userLoginReqVO.getPhone();
        Integer type = userLoginReqVO.getType();
        LoginTypeEnum loginTypeEnum = LoginTypeEnum.valueOf(type);
        Long userId = null;
        //判断登录类型
        switch (loginTypeEnum) {
            //验证码登录
            case VERIFICATION_CODE:
                String verificationCode = userLoginReqVO.getCode();
                //判断验证码是否为空
                Preconditions.checkArgument(!StringUtils.isEmpty(verificationCode), "验证码不能为空");

                String key = RedisKeyConstants.buildVerificationCodeKey(phone);
                String sentCode = (String) redisTemplate.opsForValue().get(key);

                if (!StringUtils.equals(sentCode, verificationCode)) {
                    throw new BizException(ResponseCodeEnum.VERIFICATION_CODE_ERROR);
                }
                //通过手机号查询记录
                UserDO userDO = userDOMapper.selectByPhone(phone);
                log.info("==>用户是否注册,phone:{},userDO:{}", phone, userDO);
                if (userDO == null) {
                    //未注册，则注册
                    userId = registerUser(phone);
                } else {
                    //已注册，则登录
                    userId = userDO.getId();
                }
                break;
            //密码登录
            case PASSWORD:
                //todo
                break;
        }
        //saToken登录用户，并返回登录令牌
        StpUtil.login(userId);

        //获取token令牌
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();

        //返回token
        return Response.success(tokenInfo.tokenValue);
    }

    /**
     * 系统自动注册用户
     *
     * @param phone
     * @return
     */
    public Long registerUser(String phone) {
        return transactionTemplate.execute(status -> {
            Long xiaohashuId = redisTemplate.opsForValue().increment(RedisKeyConstants.XIAOHASHU_ID_GENERATOR_KEY);
            UserDO userDO = UserDO.builder()
                    .xiaohashuId(String.valueOf(xiaohashuId))
                    .phone(phone)
                    .nickname("小红书" + xiaohashuId)
                    .status(StatusEnum.ENABLE.getValue())
                    .createTime(LocalDateTime.now())
                    .updateTime(LocalDateTime.now())
                    .isDeleted(DeletedEnum.NO.getValue())
                    .build();

            userDOMapper.insert(userDO);

            Long userId = userDO.getId();

            UserRoleDO userRoleDO = UserRoleDO.builder()
                    .userId(userId)
                    .roleId(RoleConstants.COMMON_USER_ROLE_ID)
                    .createTime(LocalDateTime.now())
                    .updateTime(LocalDateTime.now())
                    .isDeleted(DeletedEnum.NO.getValue())
                    .build();

            userRoleDOMapper.insert(userRoleDO);

            //将该角色的用户id存入redis中
            List<Long> roles = Lists.newArrayList();
            roles.add(userRoleDO.getRoleId());
            String userRolesKey = RedisKeyConstants.buildUserRoleKey(phone);
            redisTemplate.opsForValue().set(userRolesKey, JsonUtils.toJsonString(roles));
            return userId;
        });
    }
}
